package br.edu.ufcg.lsd.wbis.control.equipment;

import java.sql.Date;
import java.util.List;

import br.edu.ufcg.lsd.wbis.control.exception.CannotOpenDatabaseSessionException;
import br.edu.ufcg.lsd.wbis.control.exception.DuplicatedIdentifierException;
import br.edu.ufcg.lsd.wbis.control.exception.InvalidComponentInventoryCode;
import br.edu.ufcg.lsd.wbis.control.exception.InvalidComputerInventoryCode;
import br.edu.ufcg.lsd.wbis.control.exception.UnknownEntityException;
import br.edu.ufcg.lsd.wbis.control.user.User;
import br.edu.ufcg.lsd.wbis.control.user.UserManagerListener;

public class EquipmentManager implements UserManagerListener{

	private final EquipmentDAO equipmentDAO;
	
	/**
	 * Builds a new Equipment Manager.
	 * 
	 * @throws CannotOpenDatabaseSessionException
	 */
	public EquipmentManager() throws CannotOpenDatabaseSessionException {
		this(new HibernateEquipmentDAO());
	}

	/**
	 * Builds a new Equipment Manager with the given DAO. <br>
	 * Note: for testing purposes only!
	 * 
	 * @param dao
	 *            this User Manager's DAO
	 */
	protected EquipmentManager(EquipmentDAO dao) {

		this.equipmentDAO = dao;
	}
	
	/* Add Operations */
	
	public Router addRouter(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available, RouterType routerType, String vlan, int ports) throws DuplicatedIdentifierException{
		
		checkDuplicatedIdentifier(inventoryCode);
		
		Router router = new Router(inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available,
									routerType, vlan, ports);
		equipmentDAO.addEquipment(router);
		
		return router;
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param available
	 * @param colored
	 * @return
	 * @throws DuplicatedIdentifierException
	 */
	public Printer addPrinter(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available, boolean colored) throws DuplicatedIdentifierException{
		
		checkDuplicatedIdentifier(inventoryCode);
		
		Printer printer = new Printer(inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available, colored);
		
		equipmentDAO.addEquipment(printer);
		
		return printer;
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param available
	 * @param capacity
	 * @return
	 * @throws DuplicatedIdentifierException
	 */
	public NoBreak addNoBreak(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available, int capacity) throws DuplicatedIdentifierException {
				
		checkDuplicatedIdentifier(inventoryCode);
		
		NoBreak noBreak = new NoBreak(inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available, capacity);

		equipmentDAO.addEquipment(noBreak);
		
		return noBreak;
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param alocable
	 * @param available
	 * @param computerType
	 * @param owner
	 * @param numProcessors
	 * @param numHDs
	 * @return
	 * @throws DuplicatedIdentifierException
	 */
	public Computer addComputer(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean alocable, boolean available, ComputerType computerType, 
			User owner, int numProcessors, int numHDs) throws DuplicatedIdentifierException {
		
		checkDuplicatedIdentifier(inventoryCode);
		
		Computer computer = new Computer(inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, alocable, available,
											computerType, owner, numProcessors, numHDs);
		
		equipmentDAO.addEquipment(computer);
		
		return computer;
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param computer
	 * @param available
	 * @param frequency
	 * @param l2Cache
	 * @param cores
	 * @return
	 * @throws DuplicatedIdentifierException
	 */
	public Processor addProcessor(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available,
			String frequency, String l2Cache, int cores) throws DuplicatedIdentifierException {
		
		checkDuplicatedIdentifier(inventoryCode);
		
		Processor processor = new Processor(inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, null, available, 
											frequency, l2Cache, cores);
		
		equipmentDAO.addEquipment(processor);
		
		return processor;
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param computer
	 * @param available
	 * @param capacity
	 * @param frequency
	 * @param bus
	 * @return
	 * @throws DuplicatedIdentifierException
	 */
	public Memory addMemory(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available, int capacity, int frequency, String bus) throws DuplicatedIdentifierException {
		
		checkDuplicatedIdentifier(inventoryCode);
		
		Memory memory = new Memory(inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, null, available,
									capacity, frequency, bus);
		
		equipmentDAO.addEquipment(memory);
		
		return memory;
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param available
	 * @param computer
	 * @param memory
	 * @param frequency
	 * @param bus
	 * @return
	 * @throws DuplicatedIdentifierException
	 */
	public VideoCard addVideoCard(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available, 
			int memory, int frequency, String bus) throws DuplicatedIdentifierException {
		
		checkDuplicatedIdentifier(inventoryCode);
		
		VideoCard videoCard = new VideoCard(inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, null, available,
											memory, frequency, bus);
		
		equipmentDAO.addEquipment(videoCard);
											
		return videoCard;
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param available
	 * @param computer
	 * @param tipo
	 * @return
	 * @throws DuplicatedIdentifierException
	 */
	public Keyboard addKeyboard(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available,
			String tipo) throws DuplicatedIdentifierException {
		
		checkDuplicatedIdentifier(inventoryCode);
		
		Keyboard keyboard = new Keyboard(inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, null, available,
											tipo);
		
		equipmentDAO.addEquipment(keyboard);
		
		return keyboard;
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param available
	 * @param computer
	 * @param optical
	 * @return
	 * @throws DuplicatedIdentifierException
	 */
	public Mouse addMouse(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available, boolean optical) throws DuplicatedIdentifierException {
		
		checkDuplicatedIdentifier(inventoryCode);
		
		Mouse mouse = new Mouse(inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, null, available,
								optical);
		
		equipmentDAO.addEquipment(mouse);
		
		return mouse;
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param alocable
	 * @param available
	 * @param computer
	 * @param external
	 * @param recorder
	 * @param mediaTypes
	 * @return
	 * @throws DuplicatedIdentifierException
	 */
	public DiscDriver addDiscDriver(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean alocable, boolean available, 
			boolean external, boolean recorder, String mediaTypes) throws DuplicatedIdentifierException {
		
		checkDuplicatedIdentifier(inventoryCode);
		
		DiscDriver discDriver = new DiscDriver(inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt,
												null, alocable, available, external, recorder, mediaTypes);
		
		equipmentDAO.addEquipment(discDriver);
		
		return discDriver;
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param computer
	 * @param available
	 * @param power
	 * @return
	 * @throws DuplicatedIdentifierException
	 */
	public PowerSource addPowerSource(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available,
			int power) throws DuplicatedIdentifierException {
		
		checkDuplicatedIdentifier(inventoryCode);
		
		PowerSource powerSource = new PowerSource(inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, null,
													available, power);
		
		equipmentDAO.addEquipment(powerSource);
		
		return powerSource;
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param computer
	 * @param available
	 * @param datashow
	 * @param type
	 * @param resolution
	 * @return
	 * @throws DuplicatedIdentifierException
	 */
	public Display addDisplay(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available, 
			boolean datashow, String type, String resolution) throws DuplicatedIdentifierException {
		
		checkDuplicatedIdentifier(inventoryCode);
		
		Display display = new Display(inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, null, available,
										datashow, type, resolution);
		
		equipmentDAO.addEquipment(display);
		
		return display;
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param computer
	 * @param alocable
	 * @param available
	 * @param external
	 * @param useDescription
	 * @param capacity
	 * @param bus
	 * @return
	 * @throws DuplicatedIdentifierException
	 */
	public HardDisk addHardDisk(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean alocable, boolean available,
			boolean external, String useDescription, int capacity,
			String bus) throws DuplicatedIdentifierException {
		
		checkDuplicatedIdentifier(inventoryCode);
		
		HardDisk hd = new HardDisk(inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, null, alocable, available,
									external, useDescription, capacity, bus);
		
		equipmentDAO.addEquipment(hd);
		
		return hd;
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param alocable
	 * @param available
	 * @param type
	 * @return
	 * @throws DuplicatedIdentifierException
	 */
	public Equipment addOtherEquipment(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean alocable, boolean available, String type) throws DuplicatedIdentifierException {
		
		checkDuplicatedIdentifier(inventoryCode);
		
		Equipment otherEq = new Equipment(inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, alocable, available, type);
		
		equipmentDAO.addEquipment(otherEq);
		
		return otherEq;
	};
	
	/* Update Operations */
	
	public void updateRouter(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available, RouterType routerType, String vlan, int ports) throws UnknownEntityException{
		
		Router router = getEquipment(Router.class, inventoryCode);
		
		updateEquipment(router, inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available);
		router.setRouterType(routerType);
		router.setPorts(ports);
		
		equipmentDAO.updateEquipment(router);
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param available
	 * @param colored
	 * @throws UnknownEntityException
	 */
	public void updatePrinter(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available, boolean colored) throws UnknownEntityException{
		
		Printer printer = getEquipment(Printer.class, inventoryCode);
		
		updateEquipment(printer, inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available);
		printer.setColored(colored);

		equipmentDAO.updateEquipment(printer);
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param available
	 * @param capacity
	 * @throws UnknownEntityException
	 */
	public void updateNoBreak(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available, int capacity) throws UnknownEntityException {
		
		NoBreak noBreak = getEquipment(NoBreak.class, inventoryCode);
		
		updateEquipment(noBreak, inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available);
		noBreak.setCapacity(capacity);

		equipmentDAO.updateEquipment(noBreak);
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param alocable
	 * @param available
	 * @param computerType
	 * @param owner
	 * @param numProcessors
	 * @param numHDs
	 * @throws UnknownEntityException
	 */
	public void updateComputer(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean alocable, boolean available, ComputerType computerType, 
			User owner, int numProcessors, int numHDs) throws UnknownEntityException {
		
		Computer computer = getEquipment(Computer.class, inventoryCode);
		
		updateEquipment(computer, inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available);
		computer.setAlocable(alocable);
		computer.setComputerType(computerType);
		computer.setOwner(owner);
		computer.setNumProcessors(numProcessors);
		computer.setNumHDs(numHDs);
		
		equipmentDAO.updateEquipment(computer);
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param computer
	 * @param available
	 * @param frequency
	 * @param l2Cache
	 * @param cores
	 * @throws UnknownEntityException
	 */
	public void updateProcessor(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available,
			String frequency, String l2Cache, int cores) throws UnknownEntityException {
		
		Processor processor = getEquipment(Processor.class, inventoryCode);
		
		updateEquipment(processor, inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available);
		processor.setFrequency(frequency);
		processor.setL2Cache(l2Cache);
		processor.setCores(cores);
		
		equipmentDAO.updateEquipment(processor);
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param computer
	 * @param available
	 * @param capacity
	 * @param frequency
	 * @param bus
	 * @throws UnknownEntityException
	 */
	public void updateMemory(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available, int capacity, int frequency, String bus) throws UnknownEntityException {
		
		Memory memory = getEquipment(Memory.class, inventoryCode);
		
		updateEquipment(memory, inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available);
		memory.setBus(bus);
		
		equipmentDAO.updateEquipment(memory);
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param available
	 * @param computer
	 * @param memory
	 * @param frequency
	 * @param bus
	 * @throws UnknownEntityException
	 */
	public void updateVideoCard(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available,
			int memory, int frequency, String bus) throws UnknownEntityException {
		
		VideoCard videoCard = getEquipment(VideoCard.class, inventoryCode);
		
		updateEquipment(videoCard, inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available);
		videoCard.setMemory(memory);
		videoCard.setFrequency(frequency);
		videoCard.setBus(bus);

		equipmentDAO.updateEquipment(videoCard);
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param available
	 * @param computer
	 * @param tipo
	 * @throws UnknownEntityException
	 */
	public void updateKeyboard(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available,
			String tipo) throws UnknownEntityException {
		
		Keyboard keyboard = getEquipment(Keyboard.class, inventoryCode);
		
		updateEquipment(keyboard, inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available);
		keyboard.setTipo(tipo);

		equipmentDAO.updateEquipment(keyboard);
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param available
	 * @param computer
	 * @param optical
	 * @throws UnknownEntityException
	 */
	public void updateMouse(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available, boolean optical) throws UnknownEntityException {
		
		Mouse mouse = getEquipment(Mouse.class, inventoryCode);
		
		updateEquipment(mouse, inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available);
		mouse.setOptical(optical);
		
		equipmentDAO.updateEquipment(mouse);
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param alocable
	 * @param available
	 * @param computer
	 * @param external
	 * @param recorder
	 * @param mediaTypes
	 * @throws UnknownEntityException
	 */
	public void updateDiscDriver(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean alocable, boolean available,
			boolean external, boolean recorder, String mediaTypes) throws UnknownEntityException {
		
		DiscDriver discDriver = getEquipment(DiscDriver.class, inventoryCode);
		
		updateEquipment(discDriver, inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available);
		discDriver.setExternal(external);
		discDriver.setRecorder(recorder);
		discDriver.setMediaTypes(mediaTypes);
		
		equipmentDAO.updateEquipment(discDriver);
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param computer
	 * @param available
	 * @param power
	 * @throws UnknownEntityException
	 */
	public void updatePowerSource(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available,
			int power) throws UnknownEntityException {
		
		PowerSource powerSource = getEquipment(PowerSource.class, inventoryCode);
		
		updateEquipment(powerSource, inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available);
		powerSource.setPower(power);
		
		equipmentDAO.updateEquipment(powerSource);
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param computer
	 * @param available
	 * @param datashow
	 * @param type
	 * @param resolution
	 * @throws UnknownEntityException
	 */
	public void updateDisplay(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available, 
			boolean datashow, String type, String resolution) throws UnknownEntityException {
		
		Display display = getEquipment(Display.class, inventoryCode);
		
		updateEquipment(display, inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available);
		display.setDatashow(datashow);
		display.setDisplayType(type);
		display.setResolution(resolution);

		equipmentDAO.updateEquipment(display);
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param computer
	 * @param alocable
	 * @param available
	 * @param external
	 * @param useDescription
	 * @param capacity
	 * @param bus
	 * @throws UnknownEntityException
	 */
	public void updateHardDisk(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean alocable, boolean available,
			boolean external, String useDescription, int capacity,
			String bus) throws UnknownEntityException {
		
		HardDisk hardDisk = getEquipment(HardDisk.class, inventoryCode);
		
		updateEquipment(hardDisk, inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available);
		hardDisk.setAlocable(alocable);
		hardDisk.setExternal(external);
		hardDisk.setUseDescription(useDescription);
		hardDisk.setCapacity(capacity);
		hardDisk.setBus(bus);
		
		equipmentDAO.updateEquipment(hardDisk);
	};
	
	/**
	 * 
	 * @param inventoryCode
	 * @param brand
	 * @param serialCode
	 * @param acquisitionDate
	 * @param model
	 * @param localization
	 * @param receipt
	 * @param alocable
	 * @param available
	 * @param type
	 * @throws UnknownEntityException
	 */
	public void updateOtherEquipment(String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean alocable, boolean available, String type) throws UnknownEntityException {
		
		Equipment otherEquipment = getEquipment(Equipment.class, inventoryCode);
		
		updateEquipment(otherEquipment, inventoryCode, brand, serialCode, acquisitionDate, model, localization, receipt, available);
		otherEquipment.setType(type);
		
		equipmentDAO.updateEquipment(otherEquipment);
	};
	
	/* Remove Operations */
	
	
	public void removeEquipment(String inventoryCode) throws UnknownEntityException{
		Equipment equipment = getEquipment(Equipment.class, inventoryCode);
		if(Component.class.isAssignableFrom(equipment.getClass())){
			Component component = (Component)equipment;
			Computer computer = component.getComputer();
			computer.removeComponent(component);
			equipmentDAO.updateEquipment(computer);
		}
		equipmentDAO.removeEquipment(equipment);
	}
	
	/* Get Operations */
	
	public Router getRouter(String inventoryCode) throws UnknownEntityException{
		return getEquipment(Router.class, inventoryCode);
	}
	
	/**
	 * 
	 * @param inventoryCode
	 * @return
	 * @throws UnknownEntityException
	 */
	public Printer getPrinter(String inventoryCode) throws UnknownEntityException{
		return getEquipment(Printer.class, inventoryCode);
	}
	
	/**
	 * 
	 * @param inventoryCode
	 * @return
	 * @throws UnknownEntityException
	 */
	public NoBreak getNoBreak(String inventoryCode) throws UnknownEntityException{
		return getEquipment(NoBreak.class, inventoryCode);
	}
	
	/**
	 * 
	 * @param inventoryCode
	 * @return
	 * @throws UnknownEntityException
	 */
	public Computer getComputer(String inventoryCode) throws UnknownEntityException{
		return getEquipment(Computer.class, inventoryCode);
	}
	
	/**
	 * 
	 * @param inventoryCode
	 * @return
	 * @throws UnknownEntityException
	 */
	public Mouse getMouse(String inventoryCode) throws UnknownEntityException{
		return getEquipment(Mouse.class, inventoryCode);
	}
	
	/**
	 * 
	 * @param inventoryCode
	 * @return
	 * @throws UnknownEntityException
	 */
	public Keyboard getKeyboard(String inventoryCode) throws UnknownEntityException{
		return getEquipment(Keyboard.class, inventoryCode);
	}
	
	/**
	 * 
	 * @param inventoryCode
	 * @return
	 * @throws UnknownEntityException
	 */
	public Processor getProcessor(String inventoryCode) throws UnknownEntityException{
		return getEquipment(Processor.class, inventoryCode);
	}
	
	/**
	 * 
	 * @param inventoryCode
	 * @return
	 * @throws UnknownEntityException
	 */
	public Memory getMemory(String inventoryCode) throws UnknownEntityException{
		return getEquipment(Memory.class, inventoryCode);
	}
	
	/**
	 * 
	 * @param inventoryCode
	 * @return
	 * @throws UnknownEntityException
	 */
	public VideoCard getVideoCard(String inventoryCode) throws UnknownEntityException{
		return getEquipment(VideoCard.class, inventoryCode);
	}
	
	/**
	 * 
	 * @param inventoryCode
	 * @return
	 * @throws UnknownEntityException
	 */
	public DiscDriver getDiscDriver(String inventoryCode) throws UnknownEntityException{
		return getEquipment(DiscDriver.class, inventoryCode);
	}
	
	/**
	 * 
	 * @param inventoryCode
	 * @return
	 * @throws UnknownEntityException
	 */
	public PowerSource getPowerSource(String inventoryCode) throws UnknownEntityException{
		return getEquipment(PowerSource.class, inventoryCode);
	}
	
	/**
	 * 
	 * @param inventoryCode
	 * @return
	 * @throws UnknownEntityException
	 */
	public Display getDisplay(String inventoryCode) throws UnknownEntityException{
		return getEquipment(Display.class, inventoryCode);
	}
	
	/**
	 * 
	 * @param inventoryCode
	 * @return
	 * @throws UnknownEntityException
	 */
	public HardDisk getHardDisk(String inventoryCode) throws UnknownEntityException{
		return getEquipment(HardDisk.class, inventoryCode);
	}
	
	/**
	 * 
	 * @param inventoryCode
	 * @return
	 * @throws UnknownEntityException
	 */
	public Equipment getOtherEquipment(String inventoryCode) throws UnknownEntityException{
		return getEquipment(Equipment.class, inventoryCode, "predefined=false");
	}
	
	/**
	 * 
	 * @return
	 */
	public List<Router> getRouters(){
		return equipmentDAO.getEquipments(Router.class);
	}
	
	/**
	 * 
	 * @return
	 */
	public List<Printer> getPrinters(){
		return equipmentDAO.getEquipments(Printer.class);
	}
	
	/**
	 * 
	 * @return
	 */
	public List<NoBreak> getNoBreaks(){
		return equipmentDAO.getEquipments(NoBreak.class);
	}
	
	/**
	 * 
	 * @return
	 */
	public List<Computer> getComputers(){
		return equipmentDAO.getEquipments(Computer.class);
	}
	
	/**
	 * 
	 * @return
	 */
	public List<Mouse> getMouses(){
		return equipmentDAO.getEquipments(Mouse.class);
	}
	
	/**
	 * 
	 * @return
	 */
	public List<Keyboard> getKeyboards(){
		return equipmentDAO.getEquipments(Keyboard.class);
	}
	
	/**
	 * 
	 * @return
	 */
	public List<Processor> getProcessors(){
		return equipmentDAO.getEquipments(Processor.class);	
	}
	
	/**
	 * 
	 * @return
	 */
	public List<Memory> getMemories(){
		return equipmentDAO.getEquipments(Memory.class);
	}
	
	/**
	 * 
	 * @return
	 */
	public List<VideoCard> getVideoCards(){
		return equipmentDAO.getEquipments(VideoCard.class);
	}
	
	/**
	 * 
	 * @return
	 */
	public List<DiscDriver> getDiscDrivers(){
		return equipmentDAO.getEquipments(DiscDriver.class);
	}
	
	/**
	 * 
	 * @return
	 */
	public List<PowerSource> getPowerSources(){
		return equipmentDAO.getEquipments(PowerSource.class);
	}
	
	/**
	 * 
	 * @return
	 */
	public List<Display> getDisplays(){
		return equipmentDAO.getEquipments(Display.class);
	}
	
	/**
	 * 
	 * @return
	 */
	public List<HardDisk> getHardDisks(){
		return equipmentDAO.getEquipments(HardDisk.class);
	}
	
	/**
	 * 
	 * @return
	 */
	public List<Equipment> getOtherEquipments(){
		return equipmentDAO.getEquipments(Equipment.class, "predefined=false");
	}
	
	public List<Equipment> getAllEquipments(){
		return equipmentDAO.getEquipments(Equipment.class, "");
	}

	/* User manager listener */
	
	@Override
	public void userRemoved(User user) {
		List<Computer> userComputers = equipmentDAO.getEquipments(Computer.class, "ownerLogin=\'" + user.getLogin() + "\'");
		for (Computer computer : userComputers) {
			computer.setOwner(null);
			equipmentDAO.updateEquipment(computer);
		}
	}
	
	/* Collections operations */
	
	public void addComponentToComputer(String computerCode, String componentCode) throws InvalidComputerInventoryCode, InvalidComponentInventoryCode{
		Computer computer;
		Component component;
		
		try {
			computer = getEquipment(Computer.class, computerCode);
		} catch (UnknownEntityException e) {
			throw new InvalidComputerInventoryCode(computerCode);
		}
		
		try {
			component = getEquipment(Component.class, componentCode);
		} catch (UnknownEntityException e) {
			throw new InvalidComponentInventoryCode(componentCode);
		}
		
		if(computer.addComponent(component)){
			equipmentDAO.updateEquipment(computer);
		}
	}
	
	/**
	 * 
	 * @param computerCode
	 * @param componentCode
	 * @throws InvalidComputerInventoryCode
	 * @throws InvalidComponentInventoryCode
	 */
	public void removeComponentFromComputer(String computerCode, String componentCode) throws InvalidComputerInventoryCode, InvalidComponentInventoryCode{
		Computer computer;
		Component component;
		
		try {
			computer = getEquipment(Computer.class, computerCode);
		} catch (UnknownEntityException e) {
			throw new InvalidComputerInventoryCode(computerCode);
		}
		
		try {
			component = getEquipment(Component.class, componentCode);
		} catch (UnknownEntityException e) {
			throw new InvalidComponentInventoryCode(componentCode);
		}
		
		if(computer.removeComponent(component)){
			equipmentDAO.updateEquipment(computer);
		}
	}

	/**
	 * 
	 * @param computerCode
	 * @param service
	 * @throws InvalidComputerInventoryCode
	 */
	public void addServiceToComputer(String computerCode, String service) throws InvalidComputerInventoryCode{
		Computer computer;
		
		try {
			computer = getEquipment(Computer.class, computerCode);
		} catch (UnknownEntityException e) {
			throw new InvalidComputerInventoryCode(computerCode);
		}
		
		if(computer.addService(service)){
			equipmentDAO.updateEquipment(computer);
		}
	}
	
	/**
	 * 
	 * @param computerCode
	 * @param service
	 * @throws InvalidComputerInventoryCode
	 */
	public void removeServiceFromComputer(String computerCode, String service) throws InvalidComputerInventoryCode{
		Computer computer;
		
		try {
			computer = getEquipment(Computer.class, computerCode);
		} catch (UnknownEntityException e) {
			throw new InvalidComputerInventoryCode(computerCode);
		}
		
		if(computer.removeService(service)){
			equipmentDAO.updateEquipment(computer);
		}
	}
	
	/**
	 * 
	 * @param equipmentCode
	 * @param ipAdress
	 * @throws UnknownEntityException
	 */
	public void addIPAddressToEquipment(String equipmentCode, String ipAdress) throws UnknownEntityException {
		Equipment equipment = getEquipment(Equipment.class, equipmentCode);
		
		if(equipment.addIPAdress(ipAdress)){
			equipmentDAO.updateEquipment(equipment);
		}
	}
	
	/**
	 * 
	 * @param equipmentCode
	 * @param ipAdress
	 * @throws UnknownEntityException
	 */
	public void removeIPAddressFromEquipment(String equipmentCode, String ipAdress) throws UnknownEntityException{
		Equipment equipment = getEquipment(Equipment.class, equipmentCode);
		
		if(equipment.removeIPAdress(ipAdress)){
			equipmentDAO.updateEquipment(equipment);
		}
	}
	
	/**
	 * 
	 * @param equipmentCode
	 * @param macAddress
	 * @throws UnknownEntityException
	 */
	public void addMacAddressToEquipment(String equipmentCode, String macAddress) throws UnknownEntityException{
		Equipment equipment = getEquipment(Equipment.class, equipmentCode);
		
		if(equipment.addMacAddress(macAddress)){
			equipmentDAO.updateEquipment(equipment);
		}
	}
	
	/**
	 * 
	 * @param equipmentCode
	 * @param macAddress
	 * @throws UnknownEntityException
	 */
	public void removeMacAddressFromEquipment(String equipmentCode, String macAddress) throws UnknownEntityException{
		Equipment equipment = getEquipment(Equipment.class, equipmentCode);
		
		if(equipment.removeMacAddress(macAddress)){
			equipmentDAO.updateEquipment(equipment);
		}
	}
	
	/**
	 * 
	 * @param equipmentCode
	 * @param hostname
	 * @throws UnknownEntityException
	 */
	public void addHostNameToEquipment(String equipmentCode, String hostname) throws UnknownEntityException{
		Equipment equipment = getEquipment(Equipment.class, equipmentCode);
		
		if(equipment.addHostName(hostname)){
			equipmentDAO.updateEquipment(equipment);
		}
	}
	
	/**
	 * 
	 * @param inventoryID
	 * @param hostname
	 * @throws UnknownEntityException
	 */
	public void removeHostNameFromEquipment(String inventoryID, String hostname) throws UnknownEntityException {
		Equipment equipment = getEquipment(Equipment.class, inventoryID);
		
		if(equipment.removeHostName(hostname)){
			equipmentDAO.updateEquipment(equipment);
		}
	}

	/* Private methods */
	
	private void updateEquipment(Equipment equipment, String inventoryCode, String brand, String serialCode,
			Date acquisitionDate, String model, String localization,
			byte[] receipt, boolean available){
		
		equipment.setAcquisitionDate(acquisitionDate);
		equipment.setAvailable(available);
		equipment.setBrand(brand);
		equipment.setInventoryCode(inventoryCode);
		equipment.setLocalization(localization);
		equipment.setReceipt(receipt);
		equipment.setSerialCode(serialCode);
		equipment.setModel(model);
	}
	
	private void checkDuplicatedIdentifier(String inventoryCode) throws DuplicatedIdentifierException{
		if(equipmentDAO.getEquipment(Equipment.class, inventoryCode) != null)
			throw new DuplicatedIdentifierException(inventoryCode);
	}
	
	private <T extends Equipment> T getEquipment(Class<T> equipmentClazz, String inventoryCode) throws UnknownEntityException{
		return getEquipment(equipmentClazz, inventoryCode, "");
	}
		
	
	private <T extends Equipment> T getEquipment(Class<T> equipmentClazz, String inventoryCode, String restrictions) throws UnknownEntityException{
		T equipment = equipmentDAO.getEquipment(equipmentClazz, inventoryCode, restrictions);
		if(equipment == null){
			throw new UnknownEntityException(inventoryCode);
		}
		return equipment;
	}
	
	public static void main(String[] args) throws DuplicatedIdentifierException {
		EquipmentManager myManager = new EquipmentManager();
		
		myManager.addDisplay("1", "Samsung", "AJ37856", new Date(1234567890),
				"932B Plus", "Serra Limpa", new byte[100],  true,
				false, "LCD", "19\" Wide");
		myManager.addDiscDriver("2", "Maxtor", "M837A-AS", new Date(1234567890), "A3a",
				"Rainha", new byte[100],  true, false, false, true,
				"CD-RW/DVD-RW/Lightscribe");
		myManager.addHardDisk("3", "Samsung", "MX-8493-C", new Date(1234567890),
				"Modelo Tal", "Rainha", new byte[100],  false, false,
				false, "Hd de backup", 250, "SATA");
		myManager.addKeyboard("4", "HP", "8347JFF7S", new Date(1234567890),
				"a201", "Serra Limpa", new byte[100],  true, "ABNT2");
		myManager.addMemory("5", "Kingston", "k487", new Date(1234567890), "Sei la",
				"Rainha", new byte[100],  true, 2, 400, "DDR2");
		myManager.addMouse("6", "Microsoft", "SD7SFD00", new Date(1234567890),
				"White", "Serra L impa", new byte[100],  true, true);
		myManager.addNoBreak("7", "MAB", "MAS093", new Date(1234567890), "MODEL-A",
				"Rainha", new byte[100], true, 3);
		myManager.addPowerSource("8", "HP", "HP-37a", new Date(1234567890), "ATX",
				"Rainha", new byte[100],  true, 550);
		myManager.addPrinter("9", "HP", "h47", new Date(1234567890), "h47",
				"Corredor Terreo", new byte[100], true, false);
		myManager.addProcessor("10", "Intel", "HT-20598", new Date(1234567890),
				"Intel Code 2 Duo HT", "Rainha", new byte[100],  true,
				"2.5Ghz", "4Mb", 2);
		myManager.addRouter("11", "CISCO", "09385", new Date(1234567890), "ATQ-02",
				"Serra Limpa", new byte[100], true, RouterType.SWITCH_NETWORK,
				"Sei la", 32);
		myManager.addVideoCard("12", "GeFOrce", "GF-1398", new Date(1234567890), "FX5500",
				"Serra Limpa", new byte[100],  true, 256, 400,
				"PCI-Express");
	}
}
